package org.sample.vm.classloading;

public class ClassModifier {

	private static final int CONSTANT_POOL_COUNT_INDEX = 8;
	
	private static final int CONSTANT_UTF8_INFO = 1;
	
	private static final int[] CONSTANT_ITEM_LENGTH = 
		{ -1, -1, -1, 5, 5, 9, 9, 3, 3, 5, 5, 5, 5 };
	
	private static final int U1 = 1;
	private static final int U2 = 2;
	
	private byte[] classBytes;
	
	public ClassModifier(byte[] classBytes) {
		this.classBytes = classBytes;
	}
	
	public byte[] modifyUTF8Constant(String oldStr, String newStr) {
		int cpc = getConstantPoolCount();
		int offset = CONSTANT_POOL_COUNT_INDEX + U2;
		for (int i = 0; i < cpc; i++) {
			int tag = ByteUtils.bytes2Int(classBytes, offset, U1);
			if (tag == CONSTANT_UTF8_INFO) {
				int length = ByteUtils.bytes2Int(classBytes, offset + U1, U2);
				offset += (U1 + U2);
				String str = ByteUtils.bytes2String(classBytes, offset, length);
				if (str.equalsIgnoreCase(oldStr)) {
					byte[] strBytes = ByteUtils.string2Bytes(newStr);
					byte[] strLength = ByteUtils.int2Bytes(newStr.length(), U2);
					classBytes = ByteUtils.bytesReplace(classBytes, offset - U2, U2, strLength);
					classBytes = ByteUtils.bytesReplace(classBytes, offset, length, strBytes);
					return classBytes;
				} else {
					offset += length;
				}
			} else {
				offset += CONSTANT_ITEM_LENGTH[tag];
			}
		}
		return classBytes;
	}
	
	public int getConstantPoolCount() {
		return ByteUtils.bytes2Int(classBytes, CONSTANT_POOL_COUNT_INDEX, U2);
	}
	
}
